#pragma once
#ifndef GL_DEBUGGER_HPP
#define GL_DEBUGGER_HPP

#include "Platform.hpp"
#include <sstream>
#include <string>
#include <unordered_set>

namespace Debug {

extern void MessageCallback(GLenum source, GLenum type, GLuint id, GLenum severity,
                            GLsizei length, const GLchar *message, const void *userParam);

enum MessageSeverity { error, warn, info, hint, Count };

struct GLMessageParams {
  GLenum source;
  GLenum type;
  GLuint id;
  GLenum serverity;
  std::string message;
};

enum GLDebugSources {
  DEBUG_SOURCE_API,             // Calls to the OpenGL API
  DEBUG_SOURCE_WINDOW_SYSTEM,   // Calls to a window-system API
  DEBUG_SOURCE_SHADER_COMPILER, // A compiler for a shading language
  DEBUG_SOURCE_THIRD_PARTY,     // An application associated with OpenGL
  DEBUG_SOURCE_APPLICATION,     //	Generated by the user of this application
  DEBUG_SOURCE_OTHER,
};

enum GLDebugTypes {
  DEBUG_TYPE_ERROR,               // An error, typically from the API
  DEBUG_TYPE_DEPRECATED_BEHAVIOR, //	Some behavior marked deprecated has been used
  DEBUG_TYPE_UNDEFINED_BEHAVIOR,  //	Something has invoked undefined behavior
  DEBUG_TYPE_PORTABILITY, //	Some functionality the user relies upon is not portable
  DEBUG_TYPE_PERFORMANCE, //	Code has triggered possible performance issues
  DEBUG_TYPE_OTHER
};

inline GLenum GetGLDebugSource(GLDebugSources source);
inline GLenum GetGLDebugType(GLDebugTypes type);

inline std::string GetGLDebugSourceString(GLDebugSources source);
inline std::string GetGLDebugTypeString(GLDebugTypes type);
inline std::string GetGLDebugServerityString(MessageSeverity serverity);

class Debugger {
public:
  void Log(const GLMessageParams &params);

private:
  void GLMessageFiltering(const GLMessageParams &params);
  std::unordered_set<std::string> _messageStream;
};

} // namespace Debug

#endif